 
#import "UIViewController+BNDSLCategory.h"
#import "BNDSLNavigationBarViewController.h"
#import <objc/runtime.h>

NSString *const BNDSLViewControllerPropertyChangedNotification = @"BNDSLViewControllerPropertyChangedNotification";

static const void* BNDSLInteractivePopKey      = @"BNDSLInteractivePopKey";
static const void* BNDSLFullScreenPopKey       = @"BNDSLFullScreenPopKey";
static const void* BNDSLPopMaxDistanceKey      = @"BNDSLPopMaxDistanceKey";
static const void* BNDSLNavBarAlphaKey         = @"BNDSLNavBarAlphaKey";
static const void* BNDSLStatusBarStyleKey      = @"BNDSLStatusBarStyleKey";
static const void* BNDSLStatusBarHiddenKey     = @"BNDSLStatusBarHiddenKey";
static const void* BNDSLBackImageKey           = @"BNDSLBackImageKey";
static const void* BNDSLBackStyleKey           = @"BNDSLBackStyleKey";
static const void* BNDSLPushDelegateKey        = @"BNDSLPushDelegateKey";
static const void* BNDSLPopDelegateKey         = @"BNDSLPopDelegateKey";
static const void* BNDSLNavItemLeftSpaceKey    = @"BNDSLNavItemLeftSpaceKey";
static const void* BNDSLNavItemRightSpaceKey   = @"BNDSLNavItemRightSpaceKey";

@implementation UIViewController (BNDSLCategory)

// 方法交换
+ (void)load {
    // 保证其只执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSArray <NSString *> *oriSels = @[@"viewDidLoad",
                                          @"viewWillAppear:",
                                          @"viewDidAppear:"];
        
        [oriSels enumerateObjectsUsingBlock:^(NSString * _Nonnull oriSel, NSUInteger idx, BOOL * _Nonnull stop) {
            sl_swizzled_method(@"sl", self, oriSel, self);
        }];
    });
}

- (void)sl_viewDidLoad {
    // 初始化导航栏间距
    self.sl_navItemLeftSpace    = BNDSLNavigationBarItemSpace;
    self.sl_navItemRightSpace   = BNDSLNavigationBarItemSpace;
    
    [self sl_viewDidLoad];
}

- (void)sl_viewDidAppear:(BOOL)animated {
    [self postPropertyChangeNotification];
    
    [self sl_viewDidAppear:animated];
}

- (void)sl_viewWillAppear:(BOOL)animated {
    if ([self isKindOfClass:[UINavigationController class]]) return;
    if ([self isKindOfClass:[UITabBarController class]]) return;
    if ([self isKindOfClass:[UIAlertController class]]) return;
    if ([self isKindOfClass:[UIImagePickerController class]]) return;
    if ([self isKindOfClass:[UIVideoEditorController class]]) return;
    if ([NSStringFromClass(self.class) isEqualToString:@"PUPhotoPickerHostViewController"]) return;
    if (!self.navigationController) return;
    
    __block BOOL exist = NO;
    [BNDSLConfigure.shiledItemSpaceVCs enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[UIViewController class]]) {
            if ([self isKindOfClass:[obj class]]) {
                exist = YES;
                *stop = YES;
            }
        }else if ([obj isKindOfClass:[NSString class]]) {
            if ([NSStringFromClass(self.class) isEqualToString:obj]) {
                exist = YES;
                *stop = YES;
            }
        }
    }];
    if (exist) return;
    
    // bug fix：#41
    // 每次控制器出现的时候重置导航栏间距
    if (self.sl_navItemLeftSpace == BNDSLNavigationBarItemSpace) {
        self.sl_navItemLeftSpace = BNDSLConfigure.navItemLeftSpace;
    }
    
    if (self.sl_navItemRightSpace == BNDSLNavigationBarItemSpace) {
        self.sl_navItemRightSpace = BNDSLConfigure.navItemRightSpace;
    }
    
    // 重置navitem_space
    [BNDSLConfigure updateConfigure:^(BNDSLNavigationBarConfigure *configure) {
        configure.sl_navItemLeftSpace   = self.sl_navItemLeftSpace;
        configure.sl_navItemRightSpace  = self.sl_navItemRightSpace;
    }];
    
    [self sl_viewWillAppear:animated];
}

#pragma mark - StatusBar
- (BOOL)prefersStatusBarHidden {
    return self.sl_statusBarHidden;
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    return self.sl_statusBarStyle;
}

#pragma mark - Added Property
- (BOOL)sl_interactivePopDisabled {
    return [objc_getAssociatedObject(self, BNDSLInteractivePopKey) boolValue];
}
 
- (void)setSl_interactivePopDisabled:(BOOL)sl_interactivePopDisabled{
    objc_setAssociatedObject(self, BNDSLInteractivePopKey, @(sl_interactivePopDisabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self postPropertyChangeNotification];
}
- (BOOL)sl_fullScreenPopDisabled {
    return [objc_getAssociatedObject(self, BNDSLFullScreenPopKey) boolValue];
}
 
- (void)setSl_fullScreenPopDisabled:(BOOL)sl_fullScreenPopDisabled{
    objc_setAssociatedObject(self, BNDSLFullScreenPopKey, @(sl_fullScreenPopDisabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self postPropertyChangeNotification];
}
- (CGFloat)sl_popMaxAllowedDistanceToLeftEdge {
    return [objc_getAssociatedObject(self, BNDSLPopMaxDistanceKey) floatValue];
}
 
- (void)setSl_popMaxAllowedDistanceToLeftEdge:(CGFloat)sl_popMaxAllowedDistanceToLeftEdge{
    objc_setAssociatedObject(self, BNDSLPopMaxDistanceKey, @(sl_popMaxAllowedDistanceToLeftEdge), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self postPropertyChangeNotification];
}
- (CGFloat)sl_navBarAlpha {
    id obj = objc_getAssociatedObject(self, BNDSLNavBarAlphaKey);
    return obj ? [obj floatValue] : 1.0f;
}
 
- (void)setSl_navBarAlpha:(CGFloat)sl_navBarAlpha{
    objc_setAssociatedObject(self, BNDSLNavBarAlphaKey, @(sl_navBarAlpha), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self setNavBarAlpha:sl_navBarAlpha];
}
- (UIStatusBarStyle)sl_statusBarStyle {
    id style = objc_getAssociatedObject(self, BNDSLStatusBarStyleKey);
    return (style != nil) ? [style integerValue] : BNDSLConfigure.statusBarStyle;
}
 

- (void)setSl_statusBarStyle:(UIStatusBarStyle)sl_statusBarStyle{
    objc_setAssociatedObject(self, BNDSLStatusBarStyleKey, @(sl_statusBarStyle), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self setNeedsStatusBarAppearanceUpdate];
}
- (BOOL)sl_statusBarHidden {
    id objc = objc_getAssociatedObject(self, BNDSLStatusBarHiddenKey);
    return (objc != nil) ? [objc boolValue] : BNDSLConfigure.statusBarHidden;
}
 
- (void)setSl_statusBarHidden:(BOOL)sl_statusBarHidden{
    objc_setAssociatedObject(self, BNDSLStatusBarHiddenKey, @(sl_statusBarHidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self setNeedsStatusBarAppearanceUpdate];
}
- (BNDSLNavigationBarBackStyle)sl_backStyle {
    id style = objc_getAssociatedObject(self, BNDSLBackStyleKey);
    
    return (style != nil) ? [style integerValue] : BNDSLConfigure.backStyle;
}
 
- (void)setSl_backStyle:(BNDSLNavigationBarBackStyle)sl_backStyle{
    objc_setAssociatedObject(self, BNDSLBackStyleKey, @(sl_backStyle), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self setBackItemImage:self.sl_backImage];
}
- (UIImage *)sl_backImage {
    return objc_getAssociatedObject(self, BNDSLBackImageKey);
}
- (void)setSl_backImage:(UIImage *)sl_backImage{
    objc_setAssociatedObject(self, BNDSLBackImageKey, sl_backImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self setBackItemImage:sl_backImage];
}
- (id<BNDSLViewControllerPushDelegate>)sl_pushDelegate {
    return objc_getAssociatedObject(self, BNDSLPushDelegateKey);
}
 
- (void)setSl_pushDelegate:(id<BNDSLViewControllerPushDelegate>)sl_pushDelegate{
    objc_setAssociatedObject(self, BNDSLPushDelegateKey, sl_pushDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self postPropertyChangeNotification];
}


- (id<BNDSLViewControllerPopDelegate>)sl_popDelegate {
    return objc_getAssociatedObject(self, BNDSLPopDelegateKey);
}
 
- (void)setSl_popDelegate:(id<BNDSLViewControllerPopDelegate>)sl_popDelegate{
    objc_setAssociatedObject(self, BNDSLPopDelegateKey, sl_popDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    [self postPropertyChangeNotification];
}


- (CGFloat)sl_navItemLeftSpace {
    return [objc_getAssociatedObject(self, BNDSLNavItemLeftSpaceKey) floatValue];
}
 
- (void)setSl_navItemLeftSpace:(CGFloat)sl_navItemLeftSpace{
    objc_setAssociatedObject(self, BNDSLNavItemLeftSpaceKey, @(sl_navItemLeftSpace), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    if (sl_navItemLeftSpace == BNDSLNavigationBarItemSpace) return;
    
    [BNDSLConfigure updateConfigure:^(BNDSLNavigationBarConfigure * _Nonnull configure) {
        configure.sl_navItemLeftSpace = sl_navItemLeftSpace;
    }];
}
- (CGFloat)sl_navItemRightSpace {
    return [objc_getAssociatedObject(self, BNDSLNavItemRightSpaceKey) floatValue];
}
 
- (void)setSl_navItemRightSpace:(CGFloat)sl_navItemRightSpace{
    objc_setAssociatedObject(self, BNDSLNavItemRightSpaceKey, @(sl_navItemRightSpace), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    if (sl_navItemRightSpace == BNDSLNavigationBarItemSpace) return;
    
    [BNDSLConfigure updateConfigure:^(BNDSLNavigationBarConfigure *configure) {
        configure.sl_navItemRightSpace = sl_navItemRightSpace;
    }];
}

- (void)setNavBarAlpha:(CGFloat)alpha {
    
    UINavigationBar *navBar = nil;
    
    if ([self isKindOfClass:[BNDSLNavigationBarViewController class]]) {
        BNDSLNavigationBarViewController *vc = (BNDSLNavigationBarViewController *)self;
        
        vc.sl_navigationBar.sl_navBarBackgroundAlpha = alpha;
    }else {
        navBar = self.navigationController.navigationBar;
        
        UIView *barBackgroundView = [navBar.subviews objectAtIndex:0]; // _UIBarBackground
        UIImageView *backgroundImageView = [barBackgroundView.subviews objectAtIndex:0]; // UIImageView
        
        if (navBar.isTranslucent) {
            if (backgroundImageView != nil && backgroundImageView.image != nil) {
                barBackgroundView.alpha = alpha;
            }else {
                UIView *backgroundEffectView = [barBackgroundView.subviews objectAtIndex:1]; // UIVisualEffectView
                if (backgroundEffectView != nil) {
                    backgroundEffectView.alpha = alpha;
                }
            }
        }else {
            barBackgroundView.alpha = alpha;
        }
    }
    // 底部分割线
    navBar.clipsToBounds = alpha == 0.0;
}

- (void)setBackItemImage:(UIImage *)image {
    // 根控制器不作处理
//    if (self.navigationController.childViewControllers.count <= 1) return;
    
    // 非BNDSLNavigationBarViewController不作处理
    if (![self isKindOfClass:[BNDSLNavigationBarViewController class]]) return;
    
    if (!image) {
        if (self.sl_backStyle != BNDSLNavigationBarBackStyleNone) {
            NSString *imageName = self.sl_backStyle == BNDSLNavigationBarBackStyleBlack ? @"btn_back_black" : @"btn_back_white";
            image = [UIImage sl_imageNamed:imageName];
        }
    }
    
    // 没有image
    if (!image) return;
    
    BNDSLNavigationBarViewController *vc = (BNDSLNavigationBarViewController *)self;
    vc.sl_navLeftBarButtonItem = [UIBarButtonItem slitemWithTitle:nil image:image target:self action:@selector(backItemClick:)];
}

- (void)backItemClick:(id)sender {
    if (self.navigationController) {
        [self.navigationController popViewControllerAnimated:YES];
    }else{
        [self dismissViewControllerAnimated:true completion:nil];
    }
    
}

- (void)postPropertyChangeNotification {
    [[NSNotificationCenter defaultCenter] postNotificationName:BNDSLViewControllerPropertyChangedNotification object:@{@"viewController": self}];
}

@end
